package com.xiaogao.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaogao.autofill.annotation.FillUserInfo;
import com.xiaogao.common.entity.BaseResponse;
import com.xiaogao.common.entity.PageData;
import com.xiaogao.common.exception.BusinessException;
import com.xiaogao.common.utils.BeanListUtils;
import com.xiaogao.common.utils.token.JwtUtils;
import com.xiaogao.common.utils.PasswordUtils;
import com.xiaogao.common.utils.file.FileUtils;
import com.xiaogao.common.utils.minio.MinioUtils;
import com.xiaogao.sys.mapper.SysUserMapper;
import com.xiaogao.sys.model.SysUser;
import com.xiaogao.sys.model.SysUserRole;
import com.xiaogao.sys.request.user.AddParam;
import com.xiaogao.sys.request.user.QueryParam;
import com.xiaogao.sys.request.user.UpdateParam;
import com.xiaogao.sys.response.SysUserResponse;
import com.xiaogao.sys.response.SysUserSelect;
import com.xiaogao.sys.service.SysUserRoleService;
import com.xiaogao.sys.service.SysUserService;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.lang.String;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    private static final String DEFAULT_PASSWORD = "123456";

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private MinioUtils minioUtils;
    @Autowired
    private HttpServletRequest request;

    @FillUserInfo
    @Override
    public PageData<SysUserResponse> querySelective(Integer pageNum, Integer pageSize, QueryParam queryParam) {
        // 大分页
        LambdaQueryWrapper<SysUser> wrapper = getSysUserWrapper(queryParam);
        Integer offset = (pageNum - 1) * pageSize;
        wrapper.last(String.format("limit %d,%d", offset, pageSize));
        // 值返回id列
        wrapper.select(SysUser::getId);
        List<String> ids = sysUserMapper.selectObjs(wrapper);
        if (ids.isEmpty()) {
            return new PageData<>(new ArrayList<>(), 0L);
        }
        // 查list
        List<SysUserResponse> sysUserResponseList = sysUserMapper.queryByIds(ids);
        if (!sysUserResponseList.isEmpty()) {
            for (SysUserResponse sysUser : sysUserResponseList) {
                // todo 比较影响效率
                if(StringUtils.isNotEmpty(sysUser.getAvatar())){
                    String fileUrl = minioUtils.getFileUrl(sysUser.getAvatar());
                    sysUser.setAvatar(fileUrl);
                }
                if (sysUser.getRoleIdsStr() != null && !sysUser.getRoleIdsStr().isEmpty()) {
                    String[] split = sysUser.getRoleIdsStr().split(",");
                    List<String> roleIds = Arrays.stream(split)
                            .filter(s -> !s.trim().isEmpty())  // 过滤空字符串（如 "123,,456" 中间的逗号）
                            .collect(Collectors.toList());
                    sysUser.setRoleIds(roleIds);
                }
            }
        }
        // 查total
        LambdaQueryWrapper<SysUser> countWrapper = getSysUserWrapper(queryParam);
        Long total = sysUserMapper.selectCount(countWrapper);
        return new PageData<>(sysUserResponseList, total);
    }


    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void add(AddParam addParam) {
        // 1、queryByUsername
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getUsername, addParam.getUsername());
        SysUser dbSysUser = sysUserMapper.selectOne(wrapper);
        if (dbSysUser != null) {
            throw new BusinessException(500, String.format("用户名为：%s的用户已存在！", addParam.getUsername()));
        }
        // 2、需要添加用户
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(addParam, sysUser);
        sysUser.setPassword(PasswordUtils.encode(DEFAULT_PASSWORD));

        sysUserMapper.insert(sysUser);
        // 3、需要添加用户角色关联关系
        addUserRoleRelation(sysUser.getId(), addParam.getRoleIds());
    }


    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void update(UpdateParam updateParam) {
        SysUser dbSysUser = sysUserMapper.selectById(updateParam.getId());
        if (dbSysUser == null) {
            throw new BusinessException(500, String.format("ID为：%d的用户不存在！", updateParam.getId()));
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(updateParam, sysUser);
        sysUser.setPassword(dbSysUser.getPassword());
        sysUserMapper.updateById(sysUser);

        // 修改用户角色关联关系
        // 1、删除用户角色关联关系
        LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserRole::getUserId, updateParam.getId());
        sysUserRoleService.remove(wrapper);
        // 2、添加用户角色关联关系
        addUserRoleRelation(updateParam.getId(), updateParam.getRoleIds());
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void delete(List<Long> ids) {
        if (ids != null && !ids.isEmpty()) {
            sysUserMapper.deleteByIds(ids);
            // 删除用户角色关联关系
            LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(SysUserRole::getUserId, ids);
            sysUserRoleService.remove(wrapper);
        }
    }

    @Override
    public <T extends BaseResponse> void fillUserInfo(List<T> list) {
        if (list == null || list.isEmpty()) return;

        // 收集所有用户ID
        Set<String> userIds = new HashSet<>();
        for (T item : list) {
            if (item.getCreateBy() != null) {
                userIds.add(item.getCreateBy());
            }
            if (item.getUpdateBy() != null) {
                userIds.add(item.getUpdateBy());
            }
        }
        if (userIds.isEmpty()) return;

        // 批量查询用户信息
        List<SysUser> users = sysUserMapper.selectByIds(userIds);
        Map<String, SysUser> userMap = users.stream()
                .collect(Collectors.toMap(SysUser::getId, Function.identity()));

        // 填充信息到实体
        for (T item : list) {
            // 填充创建人信息
            SysUser createUser = userMap.get(item.getCreateBy());
            if (createUser != null) {
                item.setCreateByUsername(createUser.getUsername());
                item.setCreateByRealName(createUser.getRealName());
            }
            // 填充更新人信息
            SysUser updateUser = userMap.get(item.getUpdateBy());
            if (updateUser != null) {
                item.setUpdateByUsername(updateUser.getUsername());
                item.setUpdateByRealName(updateUser.getRealName());
            }
        }
    }

    @Override
    public String uploadAvatar(MultipartFile multipartFile) {
        if (multipartFile == null) {
            throw new BusinessException(500, "请上传头像！");
        }
        String token = request.getHeader("token");
        String loginUserId = JwtUtils.userId(token);
        SysUser sysUser = sysUserMapper.selectById(loginUserId);
        // 1、先要把minio server端存储的之前的头像干掉
        if(StringUtils.isNotEmpty(sysUser.getAvatar())){
            // 删除远端文件
            minioUtils.delete(sysUser.getAvatar());
        }
        // 2、再添加：username_${fileType}_${originalFileName}_${timestamp}.后缀
        String originalFilename = multipartFile.getOriginalFilename();  // aaa.xlsx
        String fileNameWithoutExtension = FileUtils.getFileNameWithoutExtension(originalFilename);
        String fileExtension = FileUtils.getFileExtension(originalFilename);
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); // 当前时间戳
        String fileName = String.format("%s_%s_%s_%s.%s", sysUser.getUsername(), "avatar", fileNameWithoutExtension, timestamp, fileExtension);
        minioUtils.upload(multipartFile, fileName);
        // 3、文件在minio server的文件名跟用户表的avatar字段关联起来
        sysUser.setAvatar(fileName);
        sysUserMapper.updateById(sysUser);
        // 4、需要返回全路径
        return minioUtils.getFileUrl(fileName);
    }

    @Override
    public List<SysUserSelect> select() {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(SysUser::getId,SysUser::getUsername,SysUser::getRealName);
        List<SysUser> sysUsers = sysUserMapper.selectList(wrapper);
        return BeanListUtils.copyList(sysUsers, SysUserSelect.class);
    }

    private LambdaQueryWrapper<SysUser> getSysUserWrapper(QueryParam queryParam) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotEmpty(queryParam.getUsername()), SysUser::getUsername, queryParam.getUsername());
        wrapper.like(StringUtils.isNotEmpty(queryParam.getRealName()), SysUser::getRealName, queryParam.getRealName());
        wrapper.like(StringUtils.isNotEmpty(queryParam.getPhone()), SysUser::getPhone, queryParam.getPhone());
        return wrapper;
    }

    private void addUserRoleRelation(String userId, List<String> roleIds) {
        if (roleIds != null && !roleIds.isEmpty()) {
            List<SysUserRole> sysUserRoleList = new ArrayList<>();
            for (String roleId : roleIds) {
                SysUserRole sysUserRole = new SysUserRole(userId, roleId);
                sysUserRoleList.add(sysUserRole);
            }
            sysUserRoleService.saveBatch(sysUserRoleList);
        }
    }
}
